<template>
  <div>
    <el-form-item label="编号" v-show="false">
      <el-input v-model="id"></el-input>
    </el-form-item>
    <el-form-item label="名称">
      <el-input v-model="name"></el-input>
    </el-form-item>
    <el-form-item label="跳转条件" v-show="needConditiona">
      <el-input v-model="condition" readonly @focus="openDialog"></el-input>
    </el-form-item>
    <!-- <el-form-item label="默认跳线" v-show="needConditiona">
        <el-select v-model="defaultflow" filterable placeholder="请选择" >
            <el-option label="是" :value=true></el-option>
            <el-option label="否" :value=false></el-option>
        </el-select>
    </el-form-item> -->

    <el-dialog title="跳转条件配置" :visible.sync="dialogTableVisible" :modal="false" width="1000px" @close="closeDialog">
      <el-container>
        <el-main>
          <el-container>
            <avue-crud :data="conditionDataSource"
                       v-on="onConditionDataTableEvent"
                       :option="conditionColumnsOption" :loading:="conditionLoading"></avue-crud>
          </el-container>
        </el-main>
        <el-footer style="textAlign:right">
          <el-button type="primary" @click="dialogTableVisible = false">取 消</el-button>
          <el-button type="primary" @click="saveConditions">保存并关闭</el-button>
        </el-footer>
      </el-container>
    </el-dialog>
  </div>
</template>
<script>
import bpmnHelper from '../js/helper/BpmnHelper';
import {is} from 'bpmn-js/lib/util/ModelUtil';
import AdjacencyMatrixGraph from '../js/util/AdjacencyMatrixGraph';
import propertiesConfig from "@/components/activit/configs/propertiesConfig";
import sequenceFlowConditionlOption from "@/components/activit/configs/sequenceFlowConditionlOption";

const eventDefinitionHelper = require('../js/helper/EventDefinitionHelper'),
    isAny = require('bpmn-js/lib/features/modeling/util/ModelingUtil').isAny,
    elementHelper = require('../js/helper/ElementHelper'),
    forEach = require('lodash/forEach'),
    filter = require('lodash/filter'),
    find = require('lodash/find'),
    findIndex = require('lodash/findIndex'),
    includes = require('lodash/includes'),
    replace = require('lodash/replace'),
    map = require('lodash/map'),
    uuid = require('uuid/v1');
const DEFAULT_VALUE = {
  condition: '未配置任何条件',
  logicLabel: '无'
}
export default {
  name: "SequenceFlowProperties",
  props: ['element'],
  inject: ['bpmnModeler'],

  computed: {
    onConditionDataTableEvent() {
      return {
        'on-load': this.loadCondition,
        'row-save': this.addRow,
        'row-update': this.updateRow,
        'row-del': this.removeRow,
      }
    },
    logicOptions() {
      return propertiesConfig.sequenceFlow.logicOptions;
    },
    conditionalOpts() {
      return propertiesConfig.sequenceFlow.conditionalOpts;
    },
    conditionColumnsOption() {
      return sequenceFlowConditionlOption()
    }
  },
  data() {
    return {
      conditionDataSource: [],
      conditionLoading: false,
      modeling: null,
      id: this.element.id || '',
      name: '',
      condition: DEFAULT_VALUE.condition,
      // defaultflow:false,
      //时都需要条件
      needConditiona: false,
      dialogTableVisible: false,
      //条件列表
      conditionList: [],
      formShow: false,

    }
  },
  mounted() {
    const bpmnModeler = this.bpmnModeler();
    this.modeling = bpmnModeler.get("modeling");
  },

  methods: {
    openDialog() {
      this.conditionDataSource = [];
      //加载可配置的条件列表
      // this.loadCanditionList();
      this.loadCondition();
      this.dialogTableVisible = true;
    },
    closeDialog() {
      let bo = bpmnHelper.getBo(this.element);
      this.loadCondition(bo);
    },
    addRow(row, done, loading) {
      row.id = uuid();
      this.conditionDataSource.push(row);
      done();
    },
    updateRow(row, index, done, loading) {
      this.conditionDataSource.splice(index, 1, row);
      done();
    },
    removeRow(row, index) {
      this.conditionDataSource.splice(index, 1);
    },
    //保存条件
    saveConditions() {
      let conditions = this.conditionDataSource;
      let conditionExpress = '';
      for (let index = 0; index < conditions.length; index++) {
        let condition = conditions[index];
        if (!condition) continue;
        let conditionalVal = `"${condition.conditionalVal}"`;
        if (index === conditions.length - 1 || conditions.length === 1) {
          conditionExpress += condition.variable + condition.conditionalOpt + conditionalVal;
        } else {
          conditionExpress += condition.variable + condition.conditionalOpt + conditionalVal + ' ' + condition.logic + ' ';
        }
      }
      let conditionOrConditionExpression = undefined;
      let bo = bpmnHelper.getBo(this.element);
      const bpmnModeler = this.bpmnModeler();
      const commandStack = bpmnModeler.get('commandStack');
      if (conditionExpress.length > 0) {
        let conditionalEventDefinition = eventDefinitionHelper.getConditionalEventDefinition(this.element);
        const bpmnFactory = bpmnModeler.get('bpmnFactory');
        //生成表达式
        conditionExpress = '${' + conditionExpress + '}';
        //设置表达式的值
        conditionOrConditionExpression = elementHelper.createElement(
            'bpmn:FormalExpression',
            {body: conditionExpress},
            conditionalEventDefinition || bo,
            bpmnFactory
        )
        // let source = this.element.source;
        // 如果是默认条线，移除source的属性
        // if (source && source.businessObject.defaultflow) {
        //     bpmnHelper.updatePropertiesByCmd(source,commandStack,{ 'defaultflow': false });
        // }
      }

      bpmnHelper.updatePropertiesByCmd(this.element, commandStack, {conditionExpression: conditionOrConditionExpression});
      this.dialogTableVisible = false;
    },

    loadCondition() {
      this.conditionLoading = true;
      let bo = bpmnHelper.getBo(this.element);

      let conditionalEventDefinition = eventDefinitionHelper.getConditionalEventDefinition(this.element);
      let conditionExpression = conditionalEventDefinition ? conditionalEventDefinition.condition : bo.conditionExpression;
      console.log("条件表达式加载", conditionExpression)
      this.condition = '未配置任何条件';
      if (!conditionExpression) return;
      //获取配置的条件表达
      let condition = conditionExpression.get('body');
      this.parseCondition(condition);
      this.conditionLoading = false;
    },
    parseCondition(conditionExpress) {
      let operators = ['!', '=', '>', '<'];
      let logicOperators = ['&', '|'];
      conditionExpress = conditionExpress.replace('$', '').replace('{', '').replace('}', '').replace(new RegExp('"', 'g'), '');
      this.conditionDataSource= [];
      let self = this;
      splitConditionExpress(conditionExpress);

      //截取表达时候
      function splitConditionExpress(str) {
        //正查找查找操作符
        let idx = findChar(str, true, true, logicOperators);
        if (idx === -1) {
          let row = createConditionRow(str);
          self.conditionDataSource.push(row);
        } else {
          //操作符
          let logic = str.substring(idx, idx + 2);
          let conditionExpress = str.substring(0, idx);
          let row = createConditionRow(conditionExpress, logic);
          self.conditionDataSource.push(row);
          let newStr = str.substring(idx + 2);
          splitConditionExpress(newStr);
        }
      }

      function createConditionRow(conditionExpress, logic) {
        let row = {};
        //纯表达式
        let headOptIdx = findChar(conditionExpress, true, false, operators);
        let footOptIdx = findChar(conditionExpress, false, false, operators);
        //变量
        let variable = conditionExpress.substring(0, headOptIdx).trim();
        //值
        let val = conditionExpress.substring(footOptIdx + 1, conditionExpress.length).trim();
        //操作符
        let opt = conditionExpress.substring(headOptIdx, footOptIdx + 1).trim();
        row.id = uuid();
        row.variable = variable;
        row.conditionalOpt = opt;
        row.conditionalVal = val;
        row.logic = logic
        return row;
      }

      /**
       * @description 检索第一个的操作操作符
       * @param str 需要被检索的字符串
       * @param  type 类型 true:正查找 false:反查找
       * @param report 检索的字符是否需要重复 true | false
       */
      function findChar(str, type, report, operators) {
        let index = -1;
        let len = str.length;
        if (type) {
          for (let i = 0; i < len; i++) {
            let char = str.charAt(i);
            if (includes(operators, char)) {
              //查找第一个
              if (report) {
                if (char === str.charAt(i + 1)) {
                  index = i;
                  break;
                }
              } else {
                index = i;
                break;
              }
            }
          }
        } else if (!type) {
          for (let i = (len - 1); i >= 0; i--) {
            let char = str.charAt(i);
            if (includes(operators, char)) {
              //从末尾查找最后一个
              if (report) {
                if (char === str.charAt(i - 1)) {
                  index = i;
                  break;
                }
              } else {
                index = i;
                break;
              }
            }
          }
        }
        return index;
      }
    },

    loadCanditionList() {
      let formKeys = '';
      let nodeSet = [];
      const bpmnModeler = this.bpmnModeler();
      const canvas = bpmnModeler.get('canvas');
      let children = canvas.getRootElement().children;
      let shapes = filter(children, function (c) {
        return !(c.type === 'label');
      });

      //创建有向图
      let ngGraph = new AdjacencyMatrixGraph();
      //将流程图中所有元素当作有向图的顶点加入
      forEach(shapes, function (item) {
        ngGraph.setNode(item.id);
      });
      //根据流程图的添加图的弧
      forEach(shapes, function (item) {
        //如果是连线，没有outgoing，只有target
        if (is(item, 'bpmn:SequenceFlow')) {
          ngGraph.setEdge(item.id, item.target.id);
        } else {
          forEach(item.outgoing, function (outgoing) {
            ngGraph.setEdge(item.id, outgoing.id);
          });
        }
      });
      //获取流程图中的所有可能经历过的节点
      let allPreNodes = ngGraph.allPredecessors(this.element.id);
      // 这里我设置为空，需要自己加
      this.conditionList = [];
    },


  },
  watch: {
    element: {
      deep: true,
      immediate: true,
      handler(element, oldVal) {
        this.name = element.businessObject.name;
        //显示条件配置选项
        this.needConditiona = true;
        // this.defaultflow = false;
        //获取source节点
        let sourceBo = bpmnHelper.getBo(element.source);
        if (!sourceBo) {
          return;
        }
        //获取source上的默认连线
        // let defalutSequence = element.businessObject.get('defaultflow');
        // if(defalutSequence){
        //     this.defaultflow = true;
        // }
        //加载条件
        this.loadCondition();
      }
    },

    'conditionDataSource': {
      immediate: true,
      handler: function (conditions) {
        if (!conditions) {
          this.condition = '未配置任何条件';
        } else {
          this.condition = '已配置' + conditions.length + '条件';
        }
      }
    }
  }
}
//只有网关和活动才需要配置条件
const CONDITIONAL_SOURCES = [
  'bpmn:Activity',
  'bpmn:ExclusiveGateway',
  'bpmn:InclusiveGateway',
  'bpmn:ComplexGateway'
];

function isConditionalSource(element) {
  return isAny(element, CONDITIONAL_SOURCES);
}

//判断是否需要条件配置
function idNeedCondition(element, bo) {
  if (!bo) {
    return false;
  }
  let conditionalEventDefinition = eventDefinitionHelper.getConditionalEventDefinition(element);
  if (!(is(element, 'bpmn:SequenceFlow') && isConditionalSource(element.source))
      && !conditionalEventDefinition) {
    return false;
  }
  return true;
}


</script>
<style>

</style>
